#include <iostream>
#include <unistd.h>
#include <cassert>
#include <vector>
#include <cstdlib>
#include <sys/types.h>
#include <sys/wait.h>
#include "task.hpp"

using namespace std;
const int gnum = 5;
Task t;

class EndPoint
{
public:
    EndPoint(pid_t id, int write_fd)
    : _id(id), _write_fd(write_fd)
    {}

public:
    pid_t _id;
    int _write_fd;
};

void waitCommand()
{
    while(1)
    {
        int command = 0;
        int n = read(0, &command, sizeof(int));
        if(n > 0)
        {
            t.Execute(command);
        }else if(n == 0) // 写端关闭，读取到文件结尾，自动退出
        {
            break;
        }
        else
        {
            break;
        }
    }
}
    

void createProcess(vector<EndPoint>& end_points) // 有小bug
{
    vector<int> ffd;
    for(int i = 0; i < gnum; i++)
    {
        // 1.1 创建管道
        int fd[2] = {0};
        int n = pipe(fd);
        assert(n != -1);
        (void)n;
        // 2.2 创建进程
        int id = fork();
        assert(id != -1);
        (void)id;

        // 3.关闭不需要的接口
        if(id == 0) // 子进程
        {
            for(auto front: ffd) close(front); // !!! 隐藏bug  关闭前面的写入接口

            close(fd[1]); // 关闭写入端，保留读取端
            dup2(fd[0], 0); // 所有的子进程都从标准输入读取命令

            waitCommand();
            close(fd[0]);
            exit(0);
        }

        close(fd[0]); // 关闭读取端，保留写入端
        end_points.push_back(EndPoint(id, fd[1]));

        ffd.push_back(fd[1]);
    }
}

void waitProcess(vector<EndPoint>& end_points)
{
    for(int i = 0; i < end_points.size(); ++i)
    {
        close(end_points[i]._write_fd);

        waitpid(end_points[i]._id, nullptr, 0);
        cout << "退出的进程pid: " <<end_points[i]._id << endl;
    }
    cout << "quit" << endl;
}

void ctrlProcess(vector<EndPoint>& end_points)
{
    while(true)
    {
        // 选择任务
        int command = 3;
        cin >> command;
        if(command == 3) break;
        // 选择进程
        int index = rand() % end_points.size();
        // 写入任务
        write(end_points[index]._write_fd, &command, sizeof(int));
    }
}

int main()
{
    vector<EndPoint> end_points;
    // 1.创建管道和进程
    createProcess(end_points);
    // 2.派发任务
    ctrlProcess(end_points);
    // 3.回收资源
    waitProcess(end_points);
    return 0;
}